---
title: Spring MVC
description: Spring MVC 是一个 WEB MVC 框架
---
Spring 是基础， Spring MVC 是 Spring 在 WEB 应用开发方向的扩展。
Spring MVC 是一个 WEB MVC 框架。为 WEB 项目提供了一种优秀的 MVC 分层实现方案。

## MVC 是什么
MVC 是一种分离的策略：
* 把整个应用程序中和用户进行交互的功能代码归纳在一起，这部分代码整体称为 V（View或叫视图层）；
* 把专门用来进行数据传递或数据逻辑处理的功能代码归纳在一起，称为 M （Model 或叫做模型层）；
* C 是一个叫做控制器的对象，**C 是 V 和 M 之间的桥梁**。

## 两个上下文对象

Spring提供了 IOC & DI 工厂，这个工厂对象在 Web 项目中的具体名称叫做 WebApplicationContext, 也称其为 上下文对象。用来创建 Spring MVC 项目中的各个功能组件。

Spring 建议 Spring MVC 项目中提供两个 WebApplicationContext 对象：

* 一个 WebApplicationContext 对象用来创建 Spring MVC 相关的组件，称其为 Web 上下文对象；
* 一个用来创建程序中其它的具体功能组件，称其为 Root （根）上下文对象；

![](https://img.wkq.pub/spring/5f3cfcf409478d8207000642.jpg)


## Spring MVC 核心组件
WEB 应用程序的交互模式是基于请求与响应的。在请求与响应过程中， Spring MVC 提供了众多的组件一起协调工作。

* **前端控制器**
* **用户控制器**
* **映射器**
* **适配器**： 统一控制器，让其有一致的对外接口
* **视图解析器**： 找到视图，并负责渲染视图

### 前端控制器
控制器和原生 Servlet 开发中 Servlet 的功能是一样的。

Spring MVC 中的控制器有 2 类：

* 中央控制器，或叫做前端控制器：由 Spring MVC 框架提供，对所有请求进行分流；
* 用户控制器,或叫做响应控制器：由开发者定义，用来响应用户的具体请求。

前端控制器（DispatchServlet）是 Spring MVC 中最核心的组件。
:::tip
DispatchServlet 必须在 Spring MVC 项目启动时被创建。
:::

#### 请求分流
浏览器向 Spring MVC 程序发起的所有请求都会交给 DispatcherServlet 组件，再由 DispatcherServlet 分流到具体的用户控制器；

![1](https://img.wkq.pub/spring/5f04791a09b450f611270607.jpg)

#### 调度中心

Dispatcher Servlet 是每一次请求、响应过程中的调度者。

:::tip

DIspatcherServlet 的本质是一个和 Spring MVC 程序一起启动的 Servlet。

:::

###  用户控制器

用户控制器提供具体的响应用户请求的逻辑。用户控制器由用户自定义。

#### 编写控制器

```java title='普通 Java 类即可充当控制器'
public class Hello{
    public String hello(){}
}
```

#### 映射控制器

在类前面加 @Controller 注解，此注解的作用是通知 Spring MVC 应用上下文（WebApplicationContext），控制器的创建交给你了；

```java
@Controller
@RequestMapping("/hello")
public class HelloController{
    @GetMapping
    public String hello(){
        
    }
}
```



### 映射器

映射器的作用就是检查用户的请求路径中是否存在对应的控制器组件。

![5f047b16096a77ac10910618](https://img.wkq.pub/spring/5f047b16096a77ac10910618.jpg)

使用Spring MVC 时，如果没有显式配置映射器，Spring MVC 会启用默认的映射器组件。

* RequestMappingHandlerMapping 映射器就是查找 @RequestMapping 注解映射的控制器。
* BeanNameUrlHandlerMapping 映射器的功能就是查找有没有哪一个 Bean 的名字和用户请求的路径相匹配。

### 适配器

**所谓适配器组件，其本质就是运用适配器设计模式，匹配不兼容的接口规范**。

适配器的作用就是统一不同类型的用户控制器，由适配器执行具体的 Controller。

### 视图解析器

用户控制器中的方法的返回值可以是字符串，如果没有视图解析器的解析，这个字符串就是一个字符串。如果有了视图解析器，则会把这个字符串当成一个视图的**逻辑名**，并映射到真正的物理视图。

:::tip

视图解析器和映射器有相似之处，映射器是入口时根据请求控制器逻辑名找到物理控制器，视图控制器是根据视图逻辑名找到物理视图。

:::

### 组件之间的协作方式

![5f048952098ae8b114430755](https://img.wkq.pub/spring/5f048952098ae8b114430755.jpg)

1. 浏览器的请求到达前端控制器
2. 前端控制器解析出请求路径后查询映射器，映射器返回一个执行链。
3. 前端控制器将查询到的信息发送给适配器，适配器根据信息找到相应的 Controller 并执行。
4. Controller 执行完毕后会返回给适配器执行结果
5. 适配器收到执行结果后将其返回给 DispatchServlet；
6. DispatcherServlet 接收到ModelAndView对象后，会请求 ViewResolver 对视图进行解析。
7. 
